`timescale 1ns/1ns
`define k 256
`define m 16
`define k_p_256r1 224'hfffffffeffffffffffffffffffffffff000000000000000000000001
`define p_256r1 256'hffffffff00000001000000000000000000000000ffffffffffffffffffffffff
`define n_256r1 256'hFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
`define k_p_sm2 225'h100000000000000000000000000000000ffffffff0000000000000001
`define p_sm2 256'hFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF
`define n_sm2 256'hFFFFFFFE_FFFFFFFF_FFFFFFFF_FFFFFFFF_7203DF6B_21C6052B_53BBF409_39D54123

module shared_adder(
					input [`k-1:0] a_csa,//连到外部
					input [`k+`m+2:0] s_csa,//连内部
					input [`k-1:0] b_csa,//连到外部
					input [`k+`m+2:0] c_csa,//连内部
					input [3:0] csa_sel,//连内部
					input func,//连到外部
					input [3:0] csa_p_sel,//连内部
					input [`k-1:0] a_add,//连到外部
					input [`k:0] u_add,//连内部
					input [`k-1:0] b_add,//连到外部
					//input [`k:0] v_add,//连内部
					input [`k-1:0] v_add,
					input [3:0] add_sel,//连内部
					output reg [`k+`m+2:0] csa_in1,//连接模逆，做判断信号
					output reg [`k+`m+2:0] csa_in2,//连接模逆，做判断信号
					output [`k+`m+2:0] csa_out,//连内部,位宽不确定
					output [`k:0] add_out,//连内部,位宽不确定
					output [`k-1:0] add_c//连到外部
				   );

reg [`k+`m+2:0] csa_in3;
wire [`k:0] b_csa_in;
wire [`k:0] b_add_in;
wire [`k+`m+2:0] s,c;
reg [`k:0] add_in1;
reg [`k:0] add_in2;

wire [`k:0] b_f;

assign b_f = ~b_csa + 1;

assign b_csa_in = (func == 1'b0) ? b_csa : b_f;

assign b_add_in = (func == 1'b0) ? b_add : b_f;

always @(*)
begin
	case (csa_sel[1:0])
		2'b00 	: csa_in1 = 256'b0;
		2'b01 	: csa_in1 = a_csa;
		2'b10 	: csa_in1 = s_csa;
		default : csa_in1 = 256'b0;
	endcase
end
	
always @(*)
begin
	case (csa_sel[3:2])
	2'b00 	: csa_in2 = 256'b0;
	2'b01 	: csa_in2 = b_csa_in;
	2'b10 	: csa_in2 = c_csa;
	default : csa_in2 = 256'b0;
	endcase
end

//wire [`k-1:0] sm2nk,r1nk;
//wire [`k-1:0] sm2nk;
//assign r1nk = ~(256'hFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551)+1;

//assign sm2nk = ~(`n_sm2)+1;

always @(*)
begin
	case (csa_p_sel)
	//4'b0001 : csa_in3 = 256'h0;	
	4'b0000 : csa_in3 = `k_p_256r1;//256r1的k
	4'b1001 : csa_in3 = ~(`k_p_256r1)+1;//256r1的-k
	4'b0100 : csa_in3 = `p_256r1;//256r1的p
	4'b0010 : csa_in3 = ~(`p_256r1)+1;//256r1的-p
	4'b0011 : csa_in3 = `n_256r1;//256r1的n
	4'b1000 : csa_in3 = ~(`n_256r1)+1;//256r1的-n，用作模256r1 n的加
	//4'b0110 : csa_in3 = ~(r1nk)+1;
	4'b1010 : csa_in3 = `k_p_sm2;//sm2的k
	4'b1011 : csa_in3 = ~(`k_p_sm2)+1;//sm2的-k
	4'b1100 : csa_in3 = `p_sm2;//sm2的p
	4'b1101 : csa_in3 = ~(`p_sm2)+1;//sm2的-p
	4'b0111 : csa_in3 = `n_sm2;//sm2的n
	4'b1111 : csa_in3 = ~(`n_sm2)+1;//sm2的-n，用作模sm2 n的加
	//4'b0101 : csa_in3 = ~(sm2nk)+1;//sm2 n的k的负
	4'b0101 : csa_in3 = ~(~(`n_sm2)+1)+1;
	default : csa_in3 = 256'h0;
	endcase
end

always @(*)
begin
	case(add_sel[1:0])
	2'b00 : add_in1 = 257'b0;
	2'b01 : add_in1 = a_add;
	2'b10 : add_in1 = u_add;
	default:add_in1 = 257'b0;
	endcase
end

always @(*)
begin
	case(add_sel[3:2])
	2'b00 : add_in2 = 257'b0;
	2'b01 : add_in2 = b_add_in;
	2'b10 : add_in2 = v_add;
	default:add_in2 = 257'b0;
	endcase
end

assign csa_out = (c << 1'b1) + s;

assign add_out = add_in1 + add_in2;

assign add_c = (add_out[256] == 1'b1) ? csa_out[255:0] : add_out[255:0];

CSA cadd(.a(csa_in1),.b(csa_in2),.d(csa_in3),.c(c),.s(s));

endmodule